﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using CrystalDecisions.Web;

using Danser_AJAXEnabledWebApplication.Query_Popups;
using Danser_AJAXEnabledWebApplication.User_Controls;
using Danser_AJAXEnabledWebApplication.DataSourceManagers;
using Danser_AJAXEnabledWebApplication.PageExt.Utilities;
using Danser_Control.Managers;
using Danser_Entity.Entities;
using Danser_Entity.Queries.Data;
using Danser_Entity.Queries.Filters;
using Danser_Control.Exceptions;

namespace Danser_AJAXEnabledWebApplication.User_Controls.GraphControl
{
    /// <summary>
    /// Generates reports according to selected tests, parameters and anchors
    /// </summary>
    public partial class GraphUserControl : System.Web.UI.UserControl , IGraphBuilder
    {
        #region Properties:

        private TestResultsDataSourceManager mManager = new TestResultsDataSourceManager();

        private IList<TestIntegratedData> mainTest = null;

        private IList<IList<TestIntegratedData>> anchorRef = null;

        private String mainTestIndex = null;

        private ReportDocument mRpt = null;

        private GraphData _graphData = null;

        #endregion

        #region Page Generation:
        /// <summary>
        /// load the ASP page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            GraphData graphData = GetGraphData();

            if (null != graphData.mGDmainTest)
            {
                mainTest = graphData.mGDmainTest;
                mainTestIndex = graphData.mGDmainTestIndex;
                graphData.NeedRedraw = true;
            }
            if (null != graphData.mGDanchorRef)
            {
                anchorRef = graphData.mGDanchorRef;
            } 
            
            if (!IsPostBack) //first time
            {
                PageFormatter pf = new PageFormatter();
                //feed columns to results multi select list
                pf.DisplayColumnsTemplate(testDataGridView, columnsMultiSelectList, 0, null);

                if (null != mainTest)
                {
                    DrawGraph();
                }

            }
            else
            {
                if (graphData.NeedRedraw)
                {
                    DrawGraph();
                }
            }
           

                      
        }

        /// <summary>
        /// unloads the page (to clear unused reports
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Unload(object sender, EventArgs e)
        {
            if (null != mRpt)
            {
                mRpt.Close();
                mRpt.Dispose();
            }
        }

        #endregion

        #region Report Generation

        /// <summary>
        /// Generats a report when anchors are selected
        /// </summary>
        private void GenerateReportWithAnchor()
        {
            try
            {
                CrystalReportViewer1.Visible = false;
                
                mRpt = new ReportDocument();
                //Attach relevant report
                mRpt.Load(Server.MapPath("~/User Controls/GraphControl/GraphAnchorReport.rpt"));
                mRpt.Refresh();

                // Create parameter objects
                ParameterFields mParams = new ParameterFields();
                ParameterField mParam = new ParameterField();
                ParameterDiscreteValue mDiscreteValue = new ParameterDiscreteValue();

                
                for (int i = 0; i < columnsMultiSelectList.Items.Count; i++)
                {
                    //finds the first true checkbox and sets parameter
                    // the default value is RSSI3
                    if (columnsMultiSelectList.Items[i].Selected)
                    {
                        mParam.ParameterFieldName = "sumField";
                        mDiscreteValue.Value = columnsMultiSelectList.Items[i].Text.Replace(" ", "");
                        mParam.CurrentValues.Add(mDiscreteValue);
                        mParams.Add(mParam);
                        break;
                    }                    
                }

                //Create parameter to pass main test index
                mParam = new ParameterField();
                mDiscreteValue = new ParameterDiscreteValue();
                mParam.ParameterFieldName = "mainTestIndex";
                mDiscreteValue.Value = mainTest[0].TestInfoIndex;
                mParam.CurrentValues.Add(mDiscreteValue);
                mParams.Add(mParam);


                //Add all tests to DataSet
                GraphDataSet gds = BuildDataSet(null, mainTest);
                foreach (IList<TestIntegratedData> test in anchorRef)
                {
                    gds = BuildDataSet(gds, test);
                }
                
                //Bind data and report co control
                mRpt.SetDataSource(gds);
                CrystalReportViewer1.ReportSource = mRpt;
                CrystalReportViewer1.ParameterFieldInfo = mParams;

                CrystalReportViewer1.Visible = true;
            }
            catch (Exception ex)
            {
                throw new DanserGraphException(ErrorMessages.RptGenerationErr,ex);
            }
        }

        /// <summary>
        /// Generats a report when a single test is selected
        /// </summary>
        private void GenerateReportSingleTest()
        {
            try
            {

                CrystalReportViewer1.Visible = false;
                
                mRpt = new ReportDocument();
                mRpt.Load(Server.MapPath("~/User Controls/GraphControl/GraphReport.rpt"));
                mRpt.Refresh();

                
                
                // Create parameter objects
                ParameterFields mParams = new ParameterFields();

                // Init params to be sent to report's formula                
                for (int i = 0; i < columnsMultiSelectList.Items.Count; i++)
                {
                    ParameterField mParam = new ParameterField();
                    //mParam.CurrentValues.Clear();
                    mParam.ParameterFieldName = "b_" + columnsMultiSelectList.Items[i].Text.Replace(" ", "");

                    ParameterDiscreteValue mDiscreteValue = new ParameterDiscreteValue();
                    mDiscreteValue.Value = columnsMultiSelectList.Items[i].Selected;
                    mParam.CurrentValues.Add(mDiscreteValue);
                    //mParam.HasCurrentValue = true;
                    mParams.Add(mParam);
                    
                }

                GraphDataSet gds = BuildDataSet(null, mainTest);
                mRpt.SetDataSource(gds);


                CrystalReportViewer1.ReportSource = mRpt;
                
                CrystalReportViewer1.ParameterFieldInfo = mParams;                
               
                CrystalReportViewer1.Visible = true;

            }
            catch (Exception ex) 
            {
                String innerMessage = ex.InnerException != null ? ex.InnerException.Message : ex.Message;

                String errorMesaage = String.Format(ErrorMessages.RptGenerationErr, new Object[] {innerMessage});

                throw new DanserGraphException(errorMesaage, ex);
            }
        }

        /// <summary>
        /// Converts a given test in the form of a list to a dataset 
        /// </summary>
        /// <param name="baseDataSet">The dataset to append to or null to create a dataset</param>
        /// <param name="testToAdd"> The test to add as a list</param>
        /// <returns> Returns a new dataset or an updated one</returns>
        private GraphDataSet BuildDataSet(GraphDataSet baseDataSet, IList<TestIntegratedData> testToAdd)
        {
            GraphDataSet ds = null;

            //Append data if baseDataSet isn't empty ; init DataSet otherwise
            if (baseDataSet == null)
            {
                ds = new GraphDataSet();
            }
            else 
            { 
                ds = baseDataSet; 
            }
 

            for (int i = 0; i < testToAdd.Count; i++)
            {
                DataRow ndr = ds.Tables["TestIntegratedData"].NewRow();
                ndr["Attenuation"] = testToAdd[i].Attenuation;
                ndr["RXMin"] = testToAdd[i].RXMin;
                ndr["RXAvg"] = testToAdd[i].RXAvg;
                ndr["RXMax"] = testToAdd[i].RXMax;
                ndr["TXMin"] = testToAdd[i].TXMin;
                ndr["TXAvg"] = testToAdd[i].TXAvg;
                ndr["TXMax"] = testToAdd[i].TXMax;
                ndr["RSSI1"] = testToAdd[i].RSSI1;
                ndr["RSSI2"] = testToAdd[i].RSSI2;
                ndr["RSSI3"] = testToAdd[i].RSSI3;
                ndr["TestInfoIndex"] = testToAdd[i].TestInfoIndex;
                ds.Tables["TestIntegratedData"].Rows.Add(ndr);
            }
            ds.Tables["TestIntegratedData"].AcceptChanges();
            return ds;
        }

        #endregion

        #region IGraphBuilder Members

        /// <summary>
        /// sets the chosen anchors to the graph component
        /// </summary>
        /// <param name="anchors">list of anchors</param>
        public void SetAnchors(IList<string> anchors)
        {
            if (null != anchors)
            {
                anchorRef = new List<IList<TestIntegratedData>>();
                foreach (string index in anchors)
                {
                    String filter = DBConstants.TEST_INFO_INDEX + "='" + index + "'";
                    anchorRef.Add(mManager.GetTests(filter));
                }
                GetGraphData().mGDanchorRef = anchorRef;
            }
        }

        
        /// <summary>
        /// sets the main test to the graph component
        /// </summary>
        /// <param name="testInfoIndex"></param>
        public void SetTestIndex(string testInfoIndex)
        {
            if (!String.IsNullOrEmpty(testInfoIndex))
            {
                GraphData graphData = GetGraphData();

                if (null != mainTest) 
                {
                    if (!mainTestIndex.Equals(testInfoIndex)) 
                    {
                        // a new test is chosen, empty anchor ref
                        GetGraphData().mGDanchorRef = null;
                        anchorRef = null;
                    }
                }
                mainTest = new List<TestIntegratedData>();
                String filter = DBConstants.TEST_INFO_INDEX + "='" + testInfoIndex + "'";
                mainTest = mManager.GetTests(filter);
                mainTestIndex = testInfoIndex;
                graphData.mGDmainTest = mainTest;
                graphData.mGDmainTestIndex = mainTestIndex;
            }
        }

        /// <summary>
        /// draws the graph
        /// </summary>
        public void DrawGraph()
        {
            if ((mainTest == null) || (mainTest.Count == 0)) { throw new DanserGraphException(ErrorMessages.NoTest); }
            
            if ((anchorRef == null) || (anchorRef.Count == 0))
            {
                GenerateReportSingleTest();
            }
            else
            {
                GenerateReportWithAnchor();
            }
            GetGraphData().NeedRedraw = false;
            
        }

        #endregion

        #region Helpers:

        /// <summary>
        /// confirmation of list box's items
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void ConfirmButton_Click(object sender, EventArgs e)
        {
            columnsMultiSelectList.HideSelectionList();
        }

        /// <summary>
        /// Get the graph data and initiate if nescessary
        /// </summary>
        /// <returns>this control's graph data</returns>
        private GraphData GetGraphData()
        {
            if (_graphData == null)
                _graphData = new GraphData(Session);

            return _graphData;
        }

        #endregion
    }
}